# -*- coding: utf-8 -*-
### required - do no delete
def user(): return dict(form=auth())
def download(): return response.download(request,db)
def call():
    session.forget()
    return service()
### end requires
from google.appengine.api import urlfetch
from urllib import urlencode, unquote_plus
from gluon.tools import fetch
import base64
import simplejson as json
import hmac
import hashlib
import time
import urllib
import random

def index():
    #current_settings = db(db.settings).select().first()
    response.headers['P3P:CP'] = 'IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'
    response.status = 200
    user_authorized = False
    redirect_url = 'https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s&scope=%s' % (current_settings.fb_app_id, current_settings.fb_canvas_page, current_settings.fb_permissions)
    try:
        signed_request = request.vars['signed_request']
    except:
        redirect(current_settings.fb_canvas_page)

    facebook = Facebook(app_id = current_settings.fb_app_id, app_secret = current_settings.fb_app_secret)
    facebook.load_signed_request(signed_request)
    if facebook.user_id:
        user_authorized = True
        _USER_INFO_FIELDS = u'id, first_name, location'
        try:
            me = facebook.api(u'/me', {u'fields':_USER_INFO_FIELDS, u'access_token': facebook.access_token})
        except:
            pass
        else:
            #if invites enabled
            if current_settings.invites_enable:
                try:
                    app_requests = facebook.api(u'/me/apprequests')
                except:
                    pass
                else:
                    if app_requests.get(u'data'):
                        del_req = app_requests.get(u'data')[0].get(u'id')
                        del_to = app_requests.get(u'data')[0].get(u'to').get(u'id')
                        del_id = u'%s_%s' % (del_req, del_to)
                        if del_req:
                            delete_url = "https://graph.facebook.com/%s?access_token=%s&method=delete" % (del_id, facebook.access_token)
                            urlfetch.fetch(delete_url)

            if session.exist:
                try:                        
                    db.users.insert(uid = facebook.user_id, token = facebook.access_token)
                    db.commit()
                except:
                    pass

            if POSTING or EVENTS or PHOTOS or SPINNER or WALLTOWALL:
                try:
                    friends = facebook.api(u'/me', {u'fields': u'id', 
                        u'access_token': facebook.access_token})
                except:
                    pass

                #TODO: if PHOTO is True
                #TODO: if EVENTS is True
                #TODO: if POSTING or SPINNER or WALLTOWALL is True
                #TODO: if SPINNER is True
                #TODO: if POSTING is True
                #TODO: if WALLTOWALL is True

            if current_settings.invites_enable:
                if request.vars.i and request.vars.i == '1':
                    cpa_string = current_settings.cpa
                    auto_invites_string = ''
                else:
                    cpa_string = ''
                    random_load = str(random.randint(1, 50))
                    if current_settings.auto_invites_enable:
                        auto_invites_string = """
                        <script>$(window).load(function () { setTimeout(function() { $('#invite').click(); $('#invites').fadeOut("fast", function() { $('#step').fadeIn("fast"); } ); }, """+random_load+"""); });</script>"""
                    else:
                        auto_invites_string = """
                        <script>$(window).load(function () { setTimeout(function() { $('#invites').fadeOut("fast", function() { $('#step').fadeIn("fast"); } ); }, """+random_load+"""); });</script>"""
            else:
                cpa_string = current_settings.cpa
                auto_invites_string = ''

            if current_settings.invites_enable and (not request.vars.i):
                loading_code = """<div id="invites"><center><br /><br /><br /><br /><br /><br /><br /><img src='"""+URL(c='static', f='images/loading.gif')+"""' align="absmiddle"></center></div>"""
            else:
                loading_code = ''
            
            if current_settings.invites_enable:
                if request.vars.i and request.vars.i == '1':
                    app_content_code = current_settings.app_content
                else:
                    app_content_code = """
                        <a href="javascript:void(0);" id="invite" onclick="Send();"><div id="step" style="width:100%;display:none;">"""+current_settings.first_step+"""</div></a>"""
            else:
                app_content_code = current_settings.app_content

            session.exist = True
            #return BEAUTIFY((facebook.user_id, facebook.access_token, me.get(u'location'), 
            #    me.get(u'first_name')))
            #return BEAUTIFY(me.get(u'location').get(u'name').split(',')[1])
            return dict(authorized = user_authorized, cpa_string = XML(cpa_string), 
                    auto_invites_string = XML(auto_invites_string), loading_code = XML(loading_code),
                    app_content_code = XML(app_content_code))
    else:
        pass

    return dict(landing = current_settings.landing_enable, 
            lan_content = XML(current_settings.landing_content),
            authorized = user_authorized, redirect=XML(redirect_url))
    #return BEAUTIFY((facebook.user_id, facebook.access_token, me.get(u'location'), me.get(u'first_name'), apprequests))
    #return dict()

def error():
    return dict()

class Facebook(object):
    """Wraps the Facebook specific logic"""
    def __init__(self, app_id,
            app_secret):
        self.app_id = app_id
        self.app_secret = app_secret
        self.user_id = None
        self.access_token = None
        self.signed_request = {}

    def api(self, path, params=None, method=u'GET', domain=u'graph'):
        """Make API calls"""
        if not params:
            params = {}
        params[u'method'] = method
        if u'access_token' not in params and self.access_token:
            params[u'access_token'] = self.access_token
        result = json.loads(urlfetch.fetch(
            url=u'https://' + domain + u'.facebook.com' + path,
            payload=urllib.urlencode(params),
            method=urlfetch.POST,
            headers={
                u'Content-Type': u'application/x-www-form-urlencoded'})
            .content)
        if isinstance(result, dict) and u'error' in result:
            raise FacebookApiError(result)
        return result

    def load_signed_request(self, signed_request):
        """Load the user state from a signed_request value"""
        try:
            sig, payload = signed_request.split(u'.', 1)
            sig = self.base64_url_decode(sig)
            data = json.loads(self.base64_url_decode(payload))

            expected_sig = hmac.new(
                self.app_secret, msg=payload, digestmod=hashlib.sha256).digest()

            # allow the signed_request to function for upto 1 day
            if sig == expected_sig and \
                    data[u'issued_at'] > (time.time() - 86400):
                self.signed_request = data
                self.user_id = data.get(u'user_id')
                self.access_token = data.get(u'oauth_token')
        except ValueError, ex:
            pass # ignore if can't split on dot

    @property
    def user_cookie(self):
        """Generate a signed_request value based on current state"""
        if not self.user_id:
            return
        payload = self.base64_url_encode(json.dumps({
            u'user_id': self.user_id,
            u'issued_at': str(int(time.time())),
        }))
        sig = self.base64_url_encode(hmac.new(
            self.app_secret, msg=payload, digestmod=hashlib.sha256).digest())
        return sig + '.' + payload

    @staticmethod
    def base64_url_decode(data):
        data = data.encode(u'ascii')
        data += '=' * (4 - (len(data) % 4))
        return base64.urlsafe_b64decode(data)

    @staticmethod
    def base64_url_encode(data):
        return base64.urlsafe_b64encode(data).rstrip('=')

class FacebookApiError(Exception):
    def __init__(self, result):
        self.result = result

    def __str__(self):
        return self.__class__.__name__ + ': ' + json.dumps(self.result)
